package com.geeyuu.android.utils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.params.ConnPerRouteBean;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.ByteArrayBuffer;
import org.apache.http.util.EntityUtils;

public class HttpUtil {

    private static final String TAG = "HttpUtil";
    private static final String FILE_PARAM_NAME = "myfile";
    private static HttpClient httpClient;

    public static interface HttpUploadListener {
        public void onUploadFinish(String returnFileId);
        public void onUploadFail();
    }

    public static interface HttpDownloadListener {
        public void onDownloadFinish(byte[] imgBytes, String url);
        public void onDownloadFail(String url);
    }

    private synchronized static HttpClient getDefaultHttpClient() {
        if(httpClient == null){
            HttpParams params = new BasicHttpParams();
            
            HttpConnectionParams.setConnectionTimeout(params, 1000 * 100);
            HttpConnectionParams.setSoTimeout(params, 1000 * 100);
            
            HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
            
            ConnPerRouteBean connPerRoute = new ConnPerRouteBean(200);
            ConnManagerParams.setTimeout(params, 1000 * 100);
            ConnManagerParams.setMaxTotalConnections(params, 200);
            ConnManagerParams.setMaxConnectionsPerRoute(params, connPerRoute);
            
            SchemeRegistry schemeRegistry = new SchemeRegistry();
            schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 8080));
            ThreadSafeClientConnManager tc = new ThreadSafeClientConnManager(params, schemeRegistry);
            httpClient = new DefaultHttpClient(tc, params);
        }
        return httpClient;
    }

    /**
     * 上传图片
     * 
     * @param uri
     * @param file
     * @param retryTimes
     * @param interval
     * @param httpUploadListener
     */
    public static void postFileForString(final String uri, final File file, final int retryTimes, final int interval,
            final HttpUploadListener httpUploadListener) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                LogUtil.d(TAG, "filePath: " + file.getAbsolutePath());
                HttpClient httpClient = getDefaultHttpClient();
                MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.STRICT);
                multipartEntity.addPart(FILE_PARAM_NAME, new FileBody(file));
                HttpPost post = new HttpPost(uri);
                post.setHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_CLOSE);
                post.setEntity(multipartEntity);
                HttpEntity entity = null;
                for (int i = 0; i < retryTimes; i++) {
                    try {
                        LogUtil.i(TAG, "开始提交文件, 文件长度：" + file.length());
                        HttpResponse httpResponse = httpClient.execute(post);
                        if (null != httpResponse) {
                            StatusLine statusLine = httpResponse.getStatusLine();
                            if (null != statusLine) {
                                int stateCode = statusLine.getStatusCode();
                                if (HttpStatus.SC_OK == stateCode) {
                                    entity = httpResponse.getEntity();
                                    if (null != entity) {
                                        String httpStr = EntityUtils.toString(entity, HTTP.UTF_8);
                                        if (!CommonUtil.isEmpty(httpStr) && httpStr.length() < 20) {
                                            LogUtil.i(TAG, "上传文件服务端返回字符串: " + httpStr);
                                            httpUploadListener.onUploadFinish(httpStr);
                                            post.abort();
                                            return;
                                        } else {
                                            LogUtil.e(TAG, "上传返回 httpStr is null");
                                        }
                                    } else {
                                        LogUtil.e(TAG, "上传返回 entity is null");
                                    }
                                } else {
                                    LogUtil.w(TAG, "上传返回 statusCode is unexpected, code: " + stateCode);
                                }
                            } else {
                                LogUtil.w(TAG, "上传返回 statusLine is null");
                            }
                        } else {
                            LogUtil.w(TAG, "上传返回 httpResponse is null");
                        }
                    } catch (Exception e) {
                        LogUtil.w(TAG, "上传文件有异常", e);
                    } finally {
                        if (null != entity) {
                            try {
                                entity.consumeContent();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    try {
                        Thread.sleep(interval);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                post.abort();
                httpUploadListener.onUploadFail();
            }
        }).start();
    }

    /**
     * 下载文件
     * @param uri
     * @param retryTimes
     * @param interval
     * @param httpDownloadListener
     */
    public static void getForBytes(String uri, int retryTimes, int interval, HttpDownloadListener httpDownloadListener) {
        HttpClient httpClient = getDefaultHttpClient();
        LogUtil.i(TAG, "get img url : " + uri);
        HttpGet get = new HttpGet(uri);
        get.setHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_CLOSE);
        for (int i = 0; i < retryTimes; i++) {
            try {
                HttpResponse httpResponse = httpClient.execute(get);
                if (null != httpResponse) {
                    StatusLine statusLine = httpResponse.getStatusLine();
                    if (null != statusLine) {
                        int statusCode = statusLine.getStatusCode();
                        if (statusCode == HttpStatus.SC_OK) {
                            HttpEntity httpEntity = httpResponse.getEntity();
                            if (null != httpEntity) {
                                byte[] imgBytes = toByteArray(httpEntity);
                                httpDownloadListener.onDownloadFinish(imgBytes, uri);
                                if (null != httpEntity) {
                                    try {
                                        httpEntity.consumeContent();
                                    } catch (IOException e) {
                                        e.printStackTrace();
                                    }
                                }
                                get.abort();
                                return;
                            } else {
                                LogUtil.e(TAG, "下载文件 httpEntity is null or httpEntity is not stream");
                            }
                        } else {
                            LogUtil.w(TAG, "get, status code unexpected: " + statusCode);
                        }
                    } else {
                        LogUtil.w(TAG, "get, statusLine is null");
                    }
                } else {
                    LogUtil.w(TAG, "get, httpResponse is null");
                }
            } catch (Exception e) {
                LogUtil.w(TAG, "get 异常", e);
            }
            try {
                Thread.sleep(interval);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        get.abort();
        httpDownloadListener.onDownloadFail(uri);
    }

    private synchronized static byte[] toByteArray(final HttpEntity entity) throws IOException {
        InputStream instream = entity.getContent();
        if (instream == null) {
            return new byte[] {};
        }
        if (entity.getContentLength() > Integer.MAX_VALUE) {
            return new byte[] {};
        }
        int i = (int) entity.getContentLength();
        if (i < 0) {
            i = 4096;
        }
        ByteArrayBuffer buffer = new ByteArrayBuffer(i);
        try {
            byte[] tmp = new byte[4096];
            int l;
            while ((l = instream.read(tmp)) != -1) {
                buffer.append(tmp, 0, l);
            }
        } finally {
            instream.close();
        }
        return buffer.toByteArray();
    }

    // private static HttpResponse post(String uri, HashMap<String, String>
    // paramMap, int retryTimes, int interval) {
    // HttpClient httpClient = getDefaultHttpClient();
    // ArrayList<BasicNameValuePair> formParams = new
    // ArrayList<BasicNameValuePair>();
    // Set<String> keys = paramMap.keySet();
    // for (String key : keys) {
    // formParams.add(new BasicNameValuePair(key, paramMap.get(key)));
    // }
    // HttpPost post = new HttpPost(uri);
    // try {
    // post.setEntity(new UrlEncodedFormEntity(formParams, HTTP.UTF_8));
    // } catch (UnsupportedEncodingException e) {
    // LogUtil.e(TAG, "UTF-8编码有异常", e);
    // return null;
    // }
    // for (int i = 0; i < retryTimes; i++) {
    // try {
    // HttpResponse httpResponse = httpClient.execute(post);
    // if (null != httpResponse) {
    // StatusLine statusLine = httpResponse.getStatusLine();
    // if (null != statusLine) {
    // int statusCode = statusLine.getStatusCode();
    // if (statusCode == HttpStatus.SC_OK) {
    // return httpResponse;
    // } else {
    // LogUtil.w(TAG, "post, status code unexpected: " + statusCode);
    // }
    // } else {
    // LogUtil.w(TAG, "post, statusLine is null");
    // }
    // } else {
    // LogUtil.w(TAG, "post, httpResponse is null");
    // }
    // } catch (Exception e) {
    // LogUtil.w(TAG, "post 异常", e);
    // }
    // try {
    // Thread.sleep(interval);
    // } catch (InterruptedException e) {
    // e.printStackTrace();
    // }
    // }
    // return null;
    // }

}
